﻿using System;
using System.Runtime.Serialization;
using ELearning.Common.CommonStr;

namespace ELearning.Common.Model
{
    [DataContract]
    [Serializable]
    public class ServiceResponse<T>
    {
        private ServiceResult _result;
        private T _data;
        private string _message;
        private int _code;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" />
        /// </summary>
        public ServiceResponse()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with specified <see cref="T:IdeaTech.Infrastructure.Model.ServiceResult" />
        /// </summary>
        public ServiceResponse(ServiceResult result)
        {
            _result = result;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with specified <see cref="T:IdeaTech.Infrastructure.Model.ServiceResult" /> and <paramref name="message" />
        /// </summary>
        public ServiceResponse(ServiceResult result, string message)
        {
            _result = result;
            _message = message;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with specified <see cref="T:IdeaTech.Infrastructure.Model.ServiceResult" />,<paramref name="message" /> and <paramref name="data" />.
        /// </summary>
        public ServiceResponse(ServiceResult result, string message, T data)
        {
            _result = result;
            _message = message;
            _data = data;
        }

        /// <summary>
        /// The response result , a value of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResult" />.
        /// </summary>
        [DataMember]
        public ServiceResult Result
        {
            get => _result;
            set => _result = value;
        }

        /// <summary>The response data , an instance of T.</summary>
        [DataMember(Name = "data")]
        public T Data
        {
            get => _data;
            set => _data = value;
        }

        /// <summary>The response message.</summary>
        [DataMember(Name = "message")]
        public string Message
        {
            get => _message;
            set => _message = value;
        }

        [DataMember(Name = "code")]
        public int Code
        {
            get => _code;
            set => _code = value;
        }

        /// <summary>Gets an error service reponse with null data.</summary>
        /// <param name="message">The error message.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with error result.</returns>
        public static ServiceResponse<T> ErrorResponse(string message)
        {
            return new ServiceResponse<T>(ServiceResult.Error, message) { Code = 500 };
        }

        /// <summary>Gets an error service reponse with specified data.</summary>
        /// <param name="message">The error message.</param>
        /// <param name="data">The specified append data.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with error result.</returns>
        public static ServiceResponse<T> ErrorResponse(string message, T data)
        {
            return new ServiceResponse<T>(ServiceResult.Error, message, data) { Code = 500 };
        }

        /// <summary>Gets a warning service reponse with null data.</summary>
        /// <param name="message">The warning message.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with warning result.</returns>
        public static ServiceResponse<T> WarningResponse(string message)
        {
            return new ServiceResponse<T>(ServiceResult.Warning, message) { Code = 300 };
        }

        /// <summary>Gets an warning service reponse with specified data.</summary>
        /// <param name="message">The warning message.</param>
        /// <param name="data">The specified append data.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with warning result.</returns>
        public static ServiceResponse<T> WarningResponse(string message, T data)
        {
            return new ServiceResponse<T>(ServiceResult.Warning, message, data) { Code = 300 };
        }

        /// <summary>Gets an warning service reponse with specified data.</summary>
        /// <param name="code">The warning code.</param>
        /// <param name="message">The warning message.</param>
        /// <param name="data">The specified append data.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with warning result.</returns>
        public static ServiceResponse<T> WarningResponse(int code, string message, T data)
        {
            return new ServiceResponse<T>(ServiceResult.Warning, message, data) { Code = code };
        }

        /// <summary>Gets a success service response with null data.</summary>
        /// <param name="message">The success message.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with success result.</returns>
        public static ServiceResponse<T> SuccessResponse(string message)
        {
            return new ServiceResponse<T>(ServiceResult.Success, message) { Code = 200 };
        }

        /// <summary>
        /// Gets an success service reponse with empty message and specified data.
        /// </summary>
        /// <param name="data">The specified append data.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with success result.</returns>
        public static ServiceResponse<T> SuccessResponse(T data)
        {
            return new ServiceResponse<T>(ServiceResult.Success, CommonConst.OprateSuccessStr, data) { Code = 200 };
        }

        /// <summary>Gets an success service reponse with specified data.</summary>
        /// <param name="message">The success message.</param>
        /// <param name="data">The specified append data.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with success result.</returns>
        public static ServiceResponse<T> SuccessResponse(string message, T data)
        {
            return new ServiceResponse<T>(ServiceResult.Success, message, data) { Code = 200 };
        }

        /// <summary>Gets an success service reponse with specified data.</summary>
        /// <param name="message">The success message.</param>
        /// <param name="data">The specified append data.</param>
        /// <param name="code">The success code.</param>
        /// <returns>The instance of <see cref="T:IdeaTech.Infrastructure.Model.ServiceResponse`1" /> with success result.</returns>
        public static ServiceResponse<T> SuccessResponse(string message, T data, int code)
        {
            return new ServiceResponse<T>(ServiceResult.Success, message, data) { Code = code };
        }
    }

    [DataContract]
    [Serializable]
    public enum ServiceResult
    {
        [EnumMember] Success,
        [EnumMember] Error,
        [EnumMember] Warning,
    }
}
